]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
workspace: Remove WindowOverlay in favour of new overlays of WindowClone
authorJonas Dreßler <verdre@v0yd.nl>
Tue, 2 Jun 2020 11:56:03 +0000 (13:56 +0200)
committerJonas Dreßler <verdre@v0yd.nl>
Thu, 11 Jun 2020 18:50:08 +0000 (20:50 +0200)
Start using the new overlays we introduced in the last commit and remove
the WindowOverlay class and the objects for keeping track of them in the
Workspace.

The new layout which doesn't use the -shell-close-overlap CSS property
anymore sligthly changes the position of the close button to be a bit
further away from the actual window.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1298

data/theme/gnome-shell-sass/widgets/_window-picker.scss
js/ui/workspace.js

index 466b500860d5cff38f4741271bf9389c003b3a64..2425e22bd1aab5fd8b2decfe13ae80dabdcd8636 100644 (file)
@@ -8,6 +8,7 @@ $window_thumbnail_border_color:transparentize($selected_fg_color, 0.65);
 $window_close_button_size: 24px;
 $window_close_button_padding: 3px;
 
+$window_clone_border_size: 6px;
 
 // Window picker
 .window-picker {
@@ -22,7 +23,7 @@ $window_close_button_padding: 3px;
 
 // Borders on window thumbnails
 .window-clone-border {
-  border-width: 6px;
+  border-width: $window_clone_border_size;
   border-style: solid;
   border-color: $window_thumbnail_border_color;
   border-radius: $base_border_radius + 2;
@@ -34,6 +35,7 @@ $window_close_button_padding: 3px;
 
 // Window titles
 .window-caption {
+  margin-top: $window_clone_border_size / 2;
   color: $osd_fg_color;
   background-color: $osd_bg_color;
   border:1px solid $osd_outer_borders_color;
@@ -54,8 +56,6 @@ $window_close_button_padding: 3px;
   width: $window_close_button_size;
   box-shadow: -1px 1px 5px 0px rgba(0,0,0,0.5);
 
-  -shell-close-overlap: $window_close_button_size * 0.5;
-
   &:hover {
     background-color: lighten($selected_bg_color, 5%);
   }
index a6967f302b0ff81a8c77888f22971bc661c6bd56..3367f4d8d96724fc14a88795185bc0b80d13ca64 100644 (file)
@@ -3,7 +3,6 @@
 
 const { Atk, Clutter, GLib, GObject,
         Graphene, Meta, Pango, Shell, St } = imports.gi;
-const Signals = imports.signals;
 
 const DND = imports.ui.dnd;
 const Main = imports.ui.main;
@@ -200,7 +199,6 @@ var WindowClone = GObject.registerClass({
         'drag-begin': {},
         'drag-cancelled': {},
         'drag-end': {},
-        'hide-chrome': {},
         'selected': { param_types: [GObject.TYPE_UINT] },
         'show-chrome': {},
         'size-changed': {},
@@ -445,6 +443,8 @@ var WindowClone = GObject.registerClass({
                 mode: Clutter.AnimationMode.EASE_OUT_QUAD,
             });
         });
+
+        this.emit('show-chrome');
     }
 
     hideOverlay(animate) {
@@ -629,13 +629,11 @@ var WindowClone = GObject.registerClass({
     }
 
     vfunc_enter_event(crossingEvent) {
-        this.emit('show-chrome');
+        this.showOverlay(true);
         return super.vfunc_enter_event(crossingEvent);
     }
 
     vfunc_leave_event(crossingEvent) {
-        this.emit('hide-chrome');
-
         if (this._idleHideOverlayId > 0)
             GLib.source_remove(this._idleHideOverlayId);
 
@@ -660,13 +658,12 @@ var WindowClone = GObject.registerClass({
 
     vfunc_key_focus_in() {
         super.vfunc_key_focus_in();
-        this.emit('show-chrome');
+        this.showOverlay(true);
     }
 
     vfunc_key_focus_out() {
         super.vfunc_key_focus_out();
         this.hideOverlay(true);
-        this.emit('hide-chrome');
     }
 
     vfunc_key_press_event(keyEvent) {
@@ -706,7 +703,7 @@ var WindowClone = GObject.registerClass({
                 this._draggable.startDrag(x, y, global.get_current_time(), this._dragTouchSequence, event.get_device());
             });
         } else {
-            this.emit('show-chrome');
+            this.showOverlay(true);
         }
         return true;
     }
@@ -714,6 +711,7 @@ var WindowClone = GObject.registerClass({
     _onDragBegin(_draggable, _time) {
         this._dragSlot = this._slot;
         this.inDrag = true;
+        this.hideOverlay(false);
         this.emit('drag-begin');
     }
 
@@ -743,293 +741,13 @@ var WindowClone = GObject.registerClass({
                 parent.set_child_above_sibling(this, this._stackAbove);
         }
 
+        if (this['has-pointer'])
+            this.showOverlay(true);
 
         this.emit('drag-end');
     }
 });
 
-
-/**
- * @windowClone: Corresponding window clone
- * @parentActor: The actor which will be the parent of all overlay items
- *               such as the close button and window caption
- */
-var WindowOverlay = class {
-    constructor(windowClone, parentActor) {
-        let metaWindow = windowClone.metaWindow;
-
-        this._windowClone = windowClone;
-        this._parentActor = parentActor;
-        this._hidden = false;
-
-        this._idleHideOverlayId = 0;
-
-        this.borderSize = 0;
-        this.border = new St.Bin({ style_class: 'window-clone-border' });
-
-        this.title = new St.Label({ style_class: 'window-caption',
-                                    text: this._getCaption(),
-                                    reactive: true });
-        this.title.clutter_text.ellipsize = Pango.EllipsizeMode.END;
-        windowClone.label_actor = this.title;
-
-        this._maxTitleWidth = -1;
-
-        this._updateCaptionId = metaWindow.connect('notify::title', () => {
-            this.title.text = this._getCaption();
-            this.relayout(false);
-        });
-
-        this.closeButton = new St.Button({ style_class: 'window-close' });
-        this.closeButton.add_actor(new St.Icon({ icon_name: 'window-close-symbolic' }));
-        this.closeButton._overlap = 0;
-
-        this.closeButton.connect('clicked', () => this._windowClone.deleteAll());
-
-        windowClone.connect('destroy', this._onDestroy.bind(this));
-        windowClone.connect('show-chrome', this._onShowChrome.bind(this));
-        windowClone.connect('hide-chrome', this._onHideChrome.bind(this));
-
-        this.title.hide();
-        this.closeButton.hide();
-
-        // Don't block drop targets
-        Shell.util_set_hidden_from_pick(this.border, true);
-
-        parentActor.add_actor(this.border);
-        parentActor.add_actor(this.title);
-        parentActor.add_actor(this.closeButton);
-        this.title.connect('style-changed',
-                           this._onStyleChanged.bind(this));
-        this.closeButton.connect('style-changed',
-                                 this._onStyleChanged.bind(this));
-        this.border.connect('style-changed',
-                            this._onStyleChanged.bind(this));
-
-        // Force a style change if we are already on a stage - otherwise
-        // the signal will be emitted normally when we are added
-        if (parentActor.get_stage())
-            this._onStyleChanged();
-    }
-
-    hide() {
-        this._hidden = true;
-
-        this.hideOverlay();
-    }
-
-    show() {
-        this._hidden = false;
-
-        if (this._windowClone['has-pointer'])
-            this._animateVisible();
-    }
-
-    chromeHeights() {
-        return [Math.max(this.borderSize, this.closeButton.height - this.closeButton._overlap),
-                (this.title.height - this.borderSize) / 2];
-    }
-
-    chromeWidths() {
-        return [this.borderSize,
-                Math.max(this.borderSize, this.closeButton.width - this.closeButton._overlap)];
-    }
-
-    setMaxChromeWidth(max) {
-        if (this._maxTitleWidth == max)
-            return;
-
-        this._maxTitleWidth = max;
-    }
-
-    relayout(animate) {
-        let button = this.closeButton;
-        let title = this.title;
-        let border = this.border;
-
-        button.remove_all_transitions();
-        border.remove_all_transitions();
-        title.remove_all_transitions();
-
-        title.ensure_style();
-
-        let [cloneX, cloneY, cloneWidth, cloneHeight] = this._windowClone.slot;
-
-        let layout = Meta.prefs_get_button_layout();
-        let side = layout.left_buttons.includes(Meta.ButtonFunction.CLOSE) ? St.Side.LEFT : St.Side.RIGHT;
-
-        let buttonX;
-        let buttonY = cloneY - (button.height - button._overlap);
-        if (side == St.Side.LEFT)
-            buttonX = cloneX - (button.width - button._overlap);
-        else
-            buttonX = cloneX + (cloneWidth - button._overlap);
-
-        if (animate)
-            this._animateOverlayActor(button, Math.floor(buttonX), Math.floor(buttonY), button.width);
-        else
-            button.set_position(Math.floor(buttonX), Math.floor(buttonY));
-
-        // Clutter.Actor.get_preferred_width() will return the fixed width if
-        // one is set, so we need to reset the width by calling set_width(-1),
-        // to forward the call down to StLabel.
-        // We also need to save and restore the current width, otherwise the
-        // animation starts from the wrong point.
-        let prevTitleWidth = title.width;
-        title.set_width(-1);
-
-        let [titleMinWidth, titleNatWidth] = title.get_preferred_width(-1);
-        let titleWidth = Math.max(titleMinWidth,
-                                  Math.min(titleNatWidth, this._maxTitleWidth));
-        title.width = prevTitleWidth;
-
-        let titleX = cloneX + (cloneWidth - titleWidth) / 2;
-        let titleY = cloneY + cloneHeight - (title.height - this.borderSize) / 2;
-
-        if (animate) {
-            this._animateOverlayActor(title, Math.floor(titleX), Math.floor(titleY), titleWidth);
-        } else {
-            title.width = titleWidth;
-            title.set_position(Math.floor(titleX), Math.floor(titleY));
-        }
-
-        let borderX = cloneX - this.borderSize;
-        let borderY = cloneY - this.borderSize;
-        let borderWidth = cloneWidth + 2 * this.borderSize;
-        let borderHeight = cloneHeight + 2 * this.borderSize;
-
-        if (animate) {
-            this._animateOverlayActor(this.border, borderX, borderY,
-                                      borderWidth, borderHeight);
-        } else {
-            this.border.set_position(borderX, borderY);
-            this.border.set_size(borderWidth, borderHeight);
-        }
-    }
-
-    _getCaption() {
-        let metaWindow = this._windowClone.metaWindow;
-        if (metaWindow.title)
-            return metaWindow.title;
-
-        let tracker = Shell.WindowTracker.get_default();
-        let app = tracker.get_window_app(metaWindow);
-        return app.get_name();
-    }
-
-    _animateOverlayActor(actor, x, y, width, height) {
-        let params = {
-            x, y, width,
-            duration: Overview.ANIMATION_TIME,
-            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
-        };
-
-        if (height !== undefined)
-            params.height = height;
-
-        actor.ease(params);
-    }
-
-    _windowCanClose() {
-        return this._windowClone.metaWindow.can_close() &&
-               !this._windowClone.hasAttachedDialogs();
-    }
-
-    _onDestroy() {
-        if (this._idleHideOverlayId > 0) {
-            GLib.source_remove(this._idleHideOverlayId);
-            this._idleHideOverlayId = 0;
-        }
-        this._windowClone.metaWindow.disconnect(this._updateCaptionId);
-        this.title.destroy();
-        this.closeButton.destroy();
-        this.border.destroy();
-    }
-
-    _animateVisible() {
-        this._parentActor.get_parent().set_child_above_sibling(
-            this._parentActor, null);
-
-        let toAnimate = [this.border, this.title];
-        if (this._windowCanClose())
-            toAnimate.push(this.closeButton);
-
-        toAnimate.forEach(a => {
-            a.show();
-            a.opacity = 0;
-            a.ease({
-                opacity: 255,
-                duration: WINDOW_OVERLAY_FADE_TIME,
-                mode: Clutter.AnimationMode.EASE_OUT_QUAD,
-            });
-        });
-    }
-
-    _animateInvisible() {
-        [this.closeButton, this.border, this.title].forEach(a => {
-            a.opacity = 255;
-            a.ease({
-                opacity: 0,
-                duration: WINDOW_OVERLAY_FADE_TIME,
-                mode: Clutter.AnimationMode.EASE_IN_QUAD,
-            });
-        });
-    }
-
-    _onShowChrome() {
-        // We might get enter events on the clone while the overlay is
-        // hidden, e.g. during animations, we ignore these events,
-        // as the close button will be shown as needed when the overlays
-        // are shown again
-        if (this._hidden)
-            return;
-
-        this._animateVisible();
-        this.emit('chrome-visible');
-    }
-
-    _onHideChrome() {
-        if (this._idleHideOverlayId > 0)
-            GLib.source_remove(this._idleHideOverlayId);
-
-        this._idleHideOverlayId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT, this._idleHideOverlay.bind(this));
-        GLib.Source.set_name_by_id(this._idleHideOverlayId, '[gnome-shell] this._idleHideOverlay');
-    }
-
-    _idleHideOverlay() {
-        if (this.closeButton['has-pointer'] ||
-            this.title['has-pointer'])
-            return GLib.SOURCE_CONTINUE;
-
-        if (!this._windowClone['has-pointer'])
-            this._animateInvisible();
-
-        this._idleHideOverlayId = 0;
-        return GLib.SOURCE_REMOVE;
-    }
-
-    hideOverlay() {
-        if (this._idleHideOverlayId > 0) {
-            GLib.source_remove(this._idleHideOverlayId);
-            this._idleHideOverlayId = 0;
-        }
-        this.closeButton.hide();
-        this.border.hide();
-        this.title.hide();
-    }
-
-    _onStyleChanged() {
-        let closeNode = this.closeButton.get_theme_node();
-        this.closeButton._overlap = closeNode.get_length('-shell-close-overlap');
-
-        let borderNode = this.border.get_theme_node();
-        this.borderSize = borderNode.get_border_width(St.Side.TOP);
-
-        this._parentActor.queue_relayout();
-    }
-};
-Signals.addSignalMethods(WindowOverlay.prototype);
-
 var WindowPositionFlags = {
     NONE: 0,
     INITIAL: 1 << 0,
@@ -1421,9 +1139,6 @@ class Workspace extends St.Widget {
 
         this.monitorIndex = monitorIndex;
         this._monitor = Main.layoutManager.monitors[this.monitorIndex];
-        this._windowOverlaysGroup = new Clutter.Actor();
-        // Without this the drop area will be overlapped.
-        this._windowOverlaysGroup.set_size(0, 0);
 
         if (monitorIndex != Main.layoutManager.primaryIndex)
             this.add_style_class_name('external-monitor');
@@ -1433,7 +1148,6 @@ class Workspace extends St.Widget {
         this._dropRect._delegate = this;
 
         this.add_actor(this._dropRect);
-        this.add_actor(this._windowOverlaysGroup);
 
         this.connect('destroy', this._onDestroy.bind(this));
 
@@ -1442,7 +1156,6 @@ class Workspace extends St.Widget {
         // Create clones for windows that should be
         // visible in the Overview
         this._windows = [];
-        this._windowOverlays = [];
         for (let i = 0; i < windows.length; i++) {
             if (this._isOverviewWindow(windows[i]))
                 this._addWindowClone(windows[i], true);
@@ -1627,11 +1340,6 @@ class Workspace extends St.Widget {
             const cloneHeight = cellHeight;
             clone.slot = [x, y, cloneWidth, cloneHeight];
 
-            clone.overlay.setMaxChromeWidth(cloneWidth);
-
-            if (clone.overlay && (initialPositioning || !clone.positioned))
-                clone.overlay.hide();
-
             if (!clone.positioned) {
                 // This window appeared after the overview was already up
                 // Grow the clone from the center of the slot
@@ -1662,15 +1370,13 @@ class Workspace extends St.Widget {
                     });
                 }
 
-                this._animateClone(clone, clone.overlay, x, y, cloneWidth, cloneHeight);
+                this._animateClone(clone, x, y, cloneWidth, cloneHeight);
             } else {
                 // cancel any active tweens (otherwise they might override our changes)
                 clone.remove_all_transitions();
                 clone.set_position(x, y);
                 clone.set_size(cloneWidth, cloneHeight);
                 clone.set_opacity(255);
-                clone.overlay.relayout(false);
-                this._showWindowOverlay(clone, clone.overlay);
             }
         }
     }
@@ -1694,25 +1400,13 @@ class Workspace extends St.Widget {
         }
     }
 
-    _animateClone(clone, overlay, x, y, width, height) {
+    _animateClone(clone, x, y, width, height) {
         clone.ease({
             x, y,
             width, height,
             duration: Overview.ANIMATION_TIME,
             mode: Clutter.AnimationMode.EASE_OUT_QUAD,
-            onComplete: () => {
-                this._showWindowOverlay(clone, overlay);
-            },
         });
-        clone.overlay.relayout(true);
-    }
-
-    _showWindowOverlay(clone, overlay) {
-        if (clone.inDrag)
-            return;
-
-        if (overlay && overlay._hidden)
-            overlay.show();
     }
 
     _delayedWindowRepositioning() {
@@ -1832,7 +1526,7 @@ class Workspace extends St.Widget {
             return;
         }
 
-        let [clone, overlay_] = this._addWindowClone(win, false);
+        let clone = this._addWindowClone(win, false);
 
         if (win._overviewHint) {
             let x = win._overviewHint.x - this.x;
@@ -1846,7 +1540,6 @@ class Workspace extends St.Widget {
 
             clone.set_position(x, y);
             clone.set_size(width, height);
-            clone.overlay.relayout(false);
         }
 
         this._currentLayout = null;
@@ -1914,9 +1607,7 @@ class Workspace extends St.Widget {
         for (let i = 0; i < this._windows.length; i++) {
             if (i < topMaximizedWindow) {
                 // below top-most maximized window, don't animate
-                let overlay = this._windowOverlays[i];
-                if (overlay)
-                    overlay.hide();
+                this._windows[i].hideOverlay(false);
                 this._windows[i].opacity = 0;
             } else {
                 let fromTop = topIndex - i;
@@ -1970,9 +1661,7 @@ class Workspace extends St.Widget {
         for (let i = 0; i < this._windows.length; i++) {
             if (i < topMaximizedWindow) {
                 // below top-most maximized window, don't animate
-                let overlay = this._windowOverlays[i];
-                if (overlay)
-                    overlay.hide();
+                this._windows[i].hideOverlay(false);
                 this._windows[i].opacity = 0;
             } else {
                 let fromTop = topIndex - i;
@@ -1990,10 +1679,7 @@ class Workspace extends St.Widget {
 
     _fadeWindow(index, duration, opacity) {
         let clone = this._windows[index];
-        let overlay = this._windowOverlays[index];
-
-        if (overlay)
-            overlay.hide();
+        clone.hideOverlay(false);
 
         if (clone.metaWindow.showing_on_its_workspace()) {
             clone.x = clone.boundingBox.x;
@@ -2041,10 +1727,7 @@ class Workspace extends St.Widget {
 
     _zoomWindowFromOverview(index) {
         let clone = this._windows[index];
-        let overlay = this._windowOverlays[index];
-
-        if (overlay)
-            overlay.hide();
+        clone.hideOverlay(false);
 
         if (clone.metaWindow.showing_on_its_workspace()) {
             clone.ease({
@@ -2124,42 +1807,37 @@ class Workspace extends St.Widget {
     // Create a clone of a (non-desktop) window and add it to the window list
     _addWindowClone(win, positioned) {
         let clone = new WindowClone(win, this);
-        let overlay = new WindowOverlay(clone, this._windowOverlaysGroup);
-        clone.overlay = overlay;
         clone.positioned = positioned;
 
         clone.connect('selected',
                       this._onCloneSelected.bind(this));
         clone.connect('drag-begin', () => {
             Main.overview.beginWindowDrag(clone.metaWindow);
-            overlay.hide();
         });
         clone.connect('drag-cancelled', () => {
             Main.overview.cancelledWindowDrag(clone.metaWindow);
         });
         clone.connect('drag-end', () => {
             Main.overview.endWindowDrag(clone.metaWindow);
-            overlay.show();
         });
         clone.connect('size-changed', () => {
             this._recalculateWindowPositions(WindowPositionFlags.NONE);
         });
-        clone.connect('destroy', () => {
-            this._removeWindowClone(clone.metaWindow);
-        });
-
-        this.add_actor(clone);
-
-        overlay.connect('chrome-visible', () => {
+        clone.connect('show-chrome', () => {
             let focus = global.stage.key_focus;
             if (focus == null || this.contains(focus))
                 clone.grab_key_focus();
 
-            this._windowOverlays.forEach(o => {
-                if (o != overlay)
-                    o.hideOverlay();
+            this._windows.forEach(c => {
+                if (c !== clone)
+                    c.hideOverlay(true);
             });
         });
+        clone.connect('destroy', () => {
+            this._removeWindowClone(clone.metaWindow);
+        });
+
+        this.add_child(clone);
 
         if (this._windows.length == 0)
             clone.setStackAbove(null);
@@ -2167,9 +1845,8 @@ class Workspace extends St.Widget {
             clone.setStackAbove(this._windows[this._windows.length - 1]);
 
         this._windows.push(clone);
-        this._windowOverlays.push(overlay);
 
-        return [clone, overlay];
+        return clone;
     }
 
     _removeWindowClone(metaWin) {
@@ -2179,7 +1856,6 @@ class Workspace extends St.Widget {
         if (index == -1)
             return null;
 
-        this._windowOverlays.splice(index, 1);
         return this._windows.splice(index, 1).pop();
     }
 
@@ -2250,9 +1926,9 @@ class Workspace extends St.Widget {
 
         // All of the overlays have the same chrome sizes,
         // so just pick the first one.
-        let overlay = this._windowOverlays[0];
-        let [topBorder, bottomBorder] = overlay.chromeHeights();
-        let [leftBorder, rightBorder] = overlay.chromeWidths();
+        let clone = this._windows[0];
+        let [topBorder, bottomBorder] = clone.chromeHeights();
+        let [leftBorder, rightBorder] = clone.chromeWidths();
 
         rowSpacing += (topBorder + bottomBorder) / 2;
         columnSpacing += (rightBorder + leftBorder) / 2;